#include "LoginLoginModule.h"
#include "../LoginService.h"
#include "../AccountMgr.h"
#include "base/core/com_define.h"
#include "base/core/os/time.h"
#include "base/core/Profiler.h"
#include "base/core/gamemath.h"
#include "base/net/net_pack_handle.h"
#include "Common/Utility/ServerTime.h"
#include "Common/AccountDefine.h"
#include "ProtoBuffer/AllProtocol.h"

#ifdef _MSC_VER
#pragma warning(disable:4100)
#pragma warning(disable:4244)
#pragma warning(disable:4102)
#endif

using namespace ProtoBuf;


LoginLoginModule::LoginLoginModule()
{

}

LoginLoginModule::~LoginLoginModule()
{

}


bool LoginLoginModule::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetLoginService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return false;
	}
	LogDebugFmtPrint("[login] LoginModule::Init  pMessageDispatch:%p ", pMessageDispatch);
	pMessageDispatch->registerClientHandler(EMODULE_ID_LOGIN, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_LOGIN, this);
	pMessageDispatch->registerDBProxyHandler(EMODULE_ID_LOGIN, this);

	return true;
}

void LoginLoginModule::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetLoginService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return;
	}
	pMessageDispatch->unregisterClientHandler(EMODULE_ID_LOGIN);
	pMessageDispatch->unregisterServerHandler(EMODULE_ID_LOGIN);
	pMessageDispatch->unregisterDBProxyHandler(EMODULE_ID_LOGIN);
}

void LoginLoginModule::onClientMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case CLIENT_TO_LOGIN_ACCOUNT_LOGIN:	//账号登录
		{	
			AccountLoginReq(package);
		}
		break;
	case CLIENT_TO_LOGIN_BREAK_LOGIN:	//
		{
			
		}
		break;
	default:
		break;
	}
	//package;
}

void LoginLoginModule::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case CENTER_SERVER_PROTOCOL_ACCOUNT_LOGIN_CHECK_RSP:  //中心服登录验证返回
		{
			CenterToLoginCheckRsp(package);
		}
		break;
	case CENTER_SERVER_PROTOCOL_CENTER_ACCOUNT_LOGOUT_NOTIFY:  //中心服通知账号下线
		{
			CenterToLoginNotifyLogout(package);
		}
		break;
	default:
		break;
	}
}

void LoginLoginModule::onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case DBPROXY_PROTOCOL_ACCOUNT_LOGINT_RSP:
		{
			DBRet_AccountLoginRsp(package);
		}
		break;
	default:
		break;
	}
}

bool LoginLoginModule::AccountLoginReq(RECV_PACKAGE &package)
{
	if (!g_GetLoginService()->IsRuning() || !g_GetLoginService()->IsConnectDBProxy() || !g_GetLoginService()->IsConnectCenter())
	{
		return false;
	}

	AccountLoginRequest loginReq;
	if (!loginReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[login] AccountLoginReq parse failed....");
		return false;
	}
	AccountLoginResponse loginRsp;
	uint32_t length = (uint32_t)loginReq.user_name().length();
	uint32_t id_len = (uint32_t)loginReq.user_id().length();
	if (length >= MAX_PLAT_USER_NAME_LEN || length == 0
		|| id_len >= MAX_PLAT_USER_ID_LEN || id_len == 0
		)
	{
		//长度错误
		LogDebugFmtPrint("[login] account login, length error , length=%d, id_len=%d ", length, id_len);
		g_GetLoginService()->SendClientLoginError(package.session, RET_LOGIN_BAD_USER_NAME_LEN);
		return false;
	}

	if (loginReq.has_token())
	{
		length = (uint32_t)loginReq.token().length();
		//需要验证token的长度

		//需要去平台验证token，暂时不处理
	}
	const SESSION_USER_DATA &udata = package.session->GetUserData();
	if (0 == udata.v32)
	{
		//session id 不能为0
		MMOLOG_FMT_ERROR("[login] 0 == udata.v32....user_id=%s , user_name=%s ", loginReq.user_id().c_str(), loginReq.user_name().c_str());
		return false;
	}
	if (nullptr != udata.ptr)
	{
		//此连接正在登录中，不能重复发送登录请求
		MMOLOG_FMT_ERROR("[login] nullptr != udata.ptr....user_id=%s , user_name=%s ", loginReq.user_id().c_str(), loginReq.user_name().c_str());
		return false;
	}

	//渠道用户ID = 渠道ID + 用户ID
	std::string strChannel = DEFAULT_CHANNEL_ID;
	std::string strUserID = loginReq.user_id();
	std::string strUserName = loginReq.user_name();
	std::string strChannelUserID = strChannel + strUserID;
	LoginAccount *pOnlineAccount = g_GetAccountMgr()->GetOnlineAccount(strChannelUserID.c_str());
	if (nullptr != pOnlineAccount)
	{
		if (nullptr != pOnlineAccount->session)//在线账户的session正常情况下是为空的，但是也有特殊情况
		{
			if (pOnlineAccount->session == package.session)
			{
				LogDebugFmtPrint("[login] same online account send login req...channel_user_id=%s ", strChannelUserID.c_str());
				return true;
			}

			//已经登录成功，重复登录		

			//关闭旧的客户端
			SESSION_USER_DATA old_data = pOnlineAccount->session->GetUserData();
			old_data.ptr = nullptr;
			pOnlineAccount->session->SetUserData(old_data);
			if (!g_GetLoginService()->CloseClient(pOnlineAccount->session))
			{
				MMOLOG_FMT_ERROR("[login] g_GetLoginService()->CloseClient failed.... channel_user_id=%s ", strChannelUserID.c_str());
			}
			//设置旧的连接为空
			pOnlineAccount->session = nullptr;
		}

		//设置DB账号下线
		AccountSetOnlineFlagDBRequest onlineDBReq;
		onlineDBReq.set_byonline(0);
		onlineDBReq.set_channel_user_id(strChannelUserID);
		if (!g_GetLoginService()->SendDataToDBProxy(EMODULE_ID_LOGIN,DBPROXY_PROTOCOL_ACCOUNT_SET_ONLINE_FALG_REQ, &onlineDBReq))
		{
			MMOLOG_FMT_ERROR("[login] account login req,  设置DB账号下线状态失败.... channel_user_id=%s,online_flag=%d ", strChannelUserID.c_str(), onlineDBReq.byonline());
			return false;
		}

		//设置状态开始时间
		pOnlineAccount->nTime = Time::Now().sec();
		//暂时没有平台登录，所以这里先直接设置为去数据库校验登录
		pOnlineAccount->byState = ACCOUNT_LOGIN_STATE_CHECK_LOGIN;
		//设置新session
		pOnlineAccount->session = package.session;

		//新的连接上设置 
		SESSION_USER_DATA new_data = package.session->GetUserData();
		new_data.ptr = pOnlineAccount;
		package.session->SetUserData(new_data);

		//从在线账户中删除
		g_GetAccountMgr()->DelOnlineAccount(pOnlineAccount->szChannelUserID);
		//添加到登录账户中
		g_GetAccountMgr()->AddLoginAccount(pOnlineAccount->szChannelUserID, pOnlineAccount);

		//通知中心服，账号下线
		AccountLogoutNotify logoutNotify;
		logoutNotify.set_channel_user_id(strChannelUserID);
		if (!g_GetLoginService()->SendDataToCenter(EMODULE_ID_LOGIN, CENTER_SERVER_PROTOCOL_ACCOUNT_LOGOUT_NOTIFY, &logoutNotify))
		{
			MMOLOG_FMT_ERROR("[login] account login req, 通知中心服账号下线失败 channel_user_id=%s,session=%p ", strChannelUserID.c_str(), package.session);
		}


		//请求数据库
		AccountLoginDBRequest dbReq;
		dbReq.set_plat_user_id(pOnlineAccount->szPlatUserID);
		dbReq.set_plat_user_name(pOnlineAccount->szPlatuserName);
		dbReq.set_channel(pOnlineAccount->szChannelID);
		dbReq.set_channel_user_id(pOnlineAccount->szChannelUserID);
		dbReq.set_session_id(new_data.v32);
		if (!g_GetLoginService()->SendDataToDBProxy(EMODULE_ID_LOGIN, DBPROXY_PROTOCOL_ACCOUNT_LOGINT_REQ, &dbReq))
		{
			MMOLOG_FMT_ERROR("[login] account login req, 请求DB 账号数据失败... channel_user_id=%s,session=%p,session_id=%d ", pOnlineAccount->szChannelUserID, package.session, new_data.v32);

			//从登陆账户中删除
			g_GetAccountMgr()->DelLoginAccount(pOnlineAccount->szChannelUserID);
			//清空数据
			pOnlineAccount->clear();
			//回收登录账户对象
			g_GetAccountMgr()->FreeLoginAccountObj(pOnlineAccount);

			//设置用户数据
			new_data.ptr = nullptr;
			package.session->SetUserData(new_data);
			//返回客户端登录失败
			g_GetLoginService()->SendClientLoginError(package.session, RET_FAIL);
		}
		else
		{
			LogDebugFmtPrint("[login] account login , send db request 11, channel_user_id=%s ", strChannelUserID.c_str());
		}

	}
	else
	{
		LoginAccount *pLoginAccount = g_GetAccountMgr()->GetLoginAccount(strChannelUserID.c_str());
		if (nullptr != pLoginAccount)
		{
			if (package.session == pLoginAccount->session)
			{
				//同一连接，重复发送登录请求，正常情况下不会到这里
				MMOLOG_FMT_ERROR("same session repeat account login request ....channel_user_id=%s,session=%p ", strChannelUserID.c_str(), package.session);

				return true;
			}

			//不是同一个连接，旧的连接正在登录过程中，重复登录		
			if (ACCOUNT_LOGIN_STATE_GET_GAME_SERVER == pLoginAccount->byState)
			{
				//已经发送获取逻辑服ip，端口请求，等待返回的状态，
				//这时账号在其他地方登录，需要通知中心服，账号下线
				LogDebugFmtPrint("[login] account login req, 等待中心服返回逻辑服ip,port状态,账号在其他地方登录...channel_user_id=%s ", strChannelUserID.c_str());
				AccountLogoutNotify logoutNotify;
				logoutNotify.set_channel_user_id(strChannelUserID);
				if (!g_GetLoginService()->SendDataToCenter(EMODULE_ID_LOGIN, CENTER_SERVER_PROTOCOL_ACCOUNT_LOGOUT_NOTIFY, &logoutNotify))
				{
					MMOLOG_FMT_ERROR("[login] account login req, 通知中心服账号下线失败...channel_user_id=%s ", strChannelUserID.c_str());
				}
			}

			ISession *pOldSession = pLoginAccount->session;
			if (nullptr != pOldSession)
			{
				SESSION_USER_DATA old_data = pOldSession->GetUserData();
				old_data.ptr = nullptr;
				pOldSession->SetUserData(old_data);

				LogDebugFmtPrint("[login] account login req, 账号异地登录....channel_user_id=%s ", strChannelUserID.c_str());
				//RET_LOGIN_ACCOUNT_OTHER_LOGIN   = 102;		//账号异地登录
				g_GetLoginService()->SendClientLoginError(pOldSession, RET_LOGIN_ACCOUNT_OTHER_LOGIN);
				//关闭旧连接
				g_GetLoginService()->CloseClient(pOldSession);
			}

			pLoginAccount->nTime = Time::Now().sec();
			//暂时没有平台登录，所以这里先直接设置为去数据库校验登录状态
			pLoginAccount->byState = ACCOUNT_LOGIN_STATE_CHECK_LOGIN;
			//设置session
			pLoginAccount->session = package.session;

			//session关联登录账户
			SESSION_USER_DATA new_data = package.session->GetUserData();
			new_data.ptr = pLoginAccount;
			package.session->SetUserData(new_data);

			//请求数据库
			AccountLoginDBRequest dbReq;
			dbReq.set_plat_user_id(pLoginAccount->szPlatUserID);
			dbReq.set_plat_user_name(pLoginAccount->szPlatuserName);
			dbReq.set_channel(pLoginAccount->szChannelID);
			dbReq.set_channel_user_id(pLoginAccount->szChannelUserID);
			dbReq.set_session_id(new_data.v32);
			if (!g_GetLoginService()->SendDataToDBProxy(EMODULE_ID_LOGIN, DBPROXY_PROTOCOL_ACCOUNT_LOGINT_REQ, &dbReq))
			{
				//失败
				MMOLOG_FMT_ERROR("[login] account login req, 请求DB 账号数据失败... channel_user_id=%s,session=%p,session_id=%d ", pLoginAccount->szChannelUserID, package.session, new_data.v32);
				//从登陆账户中删除
				g_GetAccountMgr()->DelLoginAccount(pLoginAccount->szChannelUserID);
				//清空数据
				pLoginAccount->clear();
				//回收登录账户对象
				g_GetAccountMgr()->FreeLoginAccountObj(pLoginAccount);

				//设置用户数据
				new_data.ptr = nullptr;
				package.session->SetUserData(new_data);
				//返回客户端登录失败
				g_GetLoginService()->SendClientLoginError(package.session, RET_FAIL);
			}
			else
			{
				LogDebugFmtPrint("[login] account login , send db request 22, channel_user_id=%s ", strChannelUserID.c_str());
			}
		}
		else
		{
			LoginAccount *pNewLoginAccount = g_GetAccountMgr()->MakeLoginAccountObj();
			if (nullptr == pNewLoginAccount)
			{
				MMOLOG_FMT_ERROR("[login] nullptr == pNewLoginAccount....");
				return false;
			}
			pNewLoginAccount->nTime = Time::Now().sec();
			//暂时没有平台登录，所以这里先直接设置为去数据库校验登录状态
			pNewLoginAccount->byState = ACCOUNT_LOGIN_STATE_CHECK_LOGIN;
			//暂时没有渠道ID，设置一个默认的渠道ID,后面有平台验证的话，平台会返回渠道ID的
			SafeCopyString(pNewLoginAccount->szChannelID, sizeof(pNewLoginAccount->szChannelID), strChannel.c_str());
			//暂时把 平台用户名和平台用户ID设置为 客户端登录时的用户名
			SafeCopyString(pNewLoginAccount->szPlatUserID, sizeof(pNewLoginAccount->szPlatUserID), strUserID.c_str());
			SafeCopyString(pNewLoginAccount->szPlatuserName, sizeof(pNewLoginAccount->szPlatuserName), strUserName.c_str());
			SafeCopyString(pNewLoginAccount->szChannelUserID, sizeof(pNewLoginAccount->szChannelUserID), strChannelUserID.c_str());

			//设置session
			pNewLoginAccount->session = package.session;

			//session关联登录账户
			SESSION_USER_DATA new_data = package.session->GetUserData();
			new_data.ptr = pNewLoginAccount;
			package.session->SetUserData(new_data);
			g_GetAccountMgr()->AddLoginAccount(pNewLoginAccount->szChannelUserID, pNewLoginAccount);

			//请求数据库
			AccountLoginDBRequest dbReq;
			dbReq.set_plat_user_id(pNewLoginAccount->szPlatUserID);
			dbReq.set_plat_user_name(pNewLoginAccount->szPlatuserName);
			dbReq.set_channel(pNewLoginAccount->szChannelID);
			dbReq.set_channel_user_id(pNewLoginAccount->szChannelUserID);
			dbReq.set_session_id(new_data.v32);
			if (!g_GetLoginService()->SendDataToDBProxy(EMODULE_ID_LOGIN, DBPROXY_PROTOCOL_ACCOUNT_LOGINT_REQ, &dbReq))
			{
				//失败
				MMOLOG_FMT_ERROR("[login] account login req, 请求DB 账号数据失败... channel_user_id=%s,session=%p,session_id=%d ", pNewLoginAccount->szChannelUserID, package.session, new_data.v32);
				//从登陆账户中删除
				g_GetAccountMgr()->DelLoginAccount(pNewLoginAccount->szChannelUserID);
				//清空数据
				pNewLoginAccount->clear();
				//回收登录账户对象
				g_GetAccountMgr()->FreeLoginAccountObj(pNewLoginAccount);

				//设置用户数据
				new_data.ptr = nullptr;
				package.session->SetUserData(new_data);
				//返回客户端登录失败
				g_GetLoginService()->SendClientLoginError(package.session, RET_FAIL);
			}
			else
			{
				LogDebugFmtPrint("[login] account login , send db request 33, channel_user_id=%s ", strChannelUserID.c_str());
			}
		}
	} // end of if (nullptr != pOnlineAccount) else

	return true;
}



//账号登录DB返回
bool LoginLoginModule::DBRet_AccountLoginRsp(RECV_PACKAGE &package)
{
	AccountLoginDBResponse rspPack;
	if (!rspPack.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[login] db ret : AccountLoginDBResponse parses failed....");
		return false;
	}
	std::string strChannelUserID = rspPack.channel_user_id();
	uint32_t nTmpSeesionID = rspPack.session_id();
	LogDebugFmtPrint("[login] db ret: account login...channel_user_id=%s ,session_id=%u ", strChannelUserID.c_str(), nTmpSeesionID);
	LoginAccount *pLoginAccount = g_GetAccountMgr()->GetLoginAccount(strChannelUserID.c_str());
	if (nullptr == pLoginAccount)
	{
		LogDebugFmtPrint("[login] db ret : nullptr == pLoginAccount....channel_user_id=%s ", strChannelUserID.c_str());
		return false;
	}
	if (nullptr == pLoginAccount->session)
	{
		//db 返回时 客户端连接已经断开了
		MMOLOG_FMT_ERROR("[login] db ret : nullptr == pLoginAccount->session....channel_user_id=%s ", strChannelUserID.c_str());
		return false;
	}

	const SESSION_USER_DATA &udata = pLoginAccount->session->GetUserData();
	if (nullptr == udata.ptr)
	{
		//登录账户关联的session已经置空了
		MMOLOG_FMT_ERROR("[login] db ret : nullptr == pLoginAccount->session....channel_user_id=%s ", strChannelUserID.c_str());
		return false;
	}
	if (nTmpSeesionID != udata.v32)
	{
		//session id 不一致,说明请求DB的session已经断开
		MMOLOG_FMT_ERROR("[login] db ret : nTmpSeesionID[%d] != udata.v32[%d]....channel_user_id=%s ", nTmpSeesionID, udata.v32, strChannelUserID.c_str());
		return false;
	}
	if (pLoginAccount->byState != ACCOUNT_LOGIN_STATE_CHECK_LOGIN)
	{
		MMOLOG_FMT_ERROR("[login] db ret : account state error, state:%d ...channel_user_id=%s  ", pLoginAccount->byState, strChannelUserID.c_str());
		return false;
	}
	uint64_t nTime = Time::Now().sec();
	uint64_t nInterSec = nTime - pLoginAccount->nTime;
	if (nInterSec > 3)
	{
		//请求到返回数据相差大于3秒，打印日志
		MMOLOG_FMT_WARN("[login] db ret : 账户[%s]登录请求DB返回时间超过 [%lld] 秒...", pLoginAccount->szChannelUserID, nInterSec);
	}
	if (RET_SUCCESS != rspPack.result())
	{
		MMOLOG_FMT_ERROR("[login] db ret : 账户[%s] 登录请求DB返回失败...", pLoginAccount->szChannelUserID);
		//设置用户数据
		ISession *session = pLoginAccount->session;
		SESSION_USER_DATA new_data = session->GetUserData();
		new_data.ptr = nullptr;
		session->SetUserData(new_data);
		//返回客户端登录失败
		g_GetLoginService()->SendClientLoginError(session, RET_FAIL);

		//从登陆账户中删除
		g_GetAccountMgr()->DelLoginAccount(pLoginAccount->szChannelUserID);
		//清空数据
		pLoginAccount->clear();
		//回收登录账户对象
		g_GetAccountMgr()->FreeLoginAccountObj(pLoginAccount);

		return false;
	}

	//返回成功，向中心服请求分配逻辑服 ip,port,以及登录逻辑服 token
	AccountLoginCheckReq loginCheckReq;
	loginCheckReq.set_channel_user_id(strChannelUserID);
	loginCheckReq.set_session_id(udata.v32);
	if (!g_GetLoginService()->SendDataToCenter(EMODULE_ID_LOGIN, CENTER_SERVER_PROTOCOL_ACCOUNT_LOGIN_CHECK_REQ, &loginCheckReq))
	{
		MMOLOG_FMT_ERROR("[login] db ret : 账户[%s]登录DB返回成功,向中心服登录获取逻辑服信息请求失败...", pLoginAccount->szChannelUserID);

		//设置用户数据
		ISession *session = pLoginAccount->session;
		SESSION_USER_DATA new_data = session->GetUserData();
		new_data.ptr = nullptr;
		session->SetUserData(new_data);
		//返回客户端登录失败
		g_GetLoginService()->SendClientLoginError(session, RET_FAIL);

		//从登陆账户中删除
		g_GetAccountMgr()->DelLoginAccount(pLoginAccount->szChannelUserID);
		//清空数据
		pLoginAccount->clear();
		//回收登录账户对象
		g_GetAccountMgr()->FreeLoginAccountObj(pLoginAccount);

		return false;
	}
	LogDebugFmtPrint("[login] db ret : account[%s] send to center request ip and port..", strChannelUserID.c_str());
	pLoginAccount->byState = ACCOUNT_LOGIN_STATE_GET_GAME_SERVER;
	pLoginAccount->nTime = nTime;

	return true;
}
//中心服通知登录服账号下线
bool LoginLoginModule::CenterToLoginNotifyLogout(RECV_PACKAGE &package)
{
	CenterAccountLogoutNotify notify;
	if (!notify.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[login] CenterAccountLogoutNotify parse failed.... ");
		return false;
	}
	std::string strChannelUserID = notify.channel_user_id();
	LoginAccount *pAccount = g_GetAccountMgr()->GetOnlineAccount(strChannelUserID.c_str());
	if (nullptr != pAccount)
	{
		//设置DB账号下线
		AccountSetOnlineFlagDBRequest onlineDBReq;
		onlineDBReq.set_byonline(0);
		onlineDBReq.set_channel_user_id(strChannelUserID);
		if (!g_GetLoginService()->SendDataToDBProxy(EMODULE_ID_LOGIN, DBPROXY_PROTOCOL_ACCOUNT_SET_ONLINE_FALG_REQ, &onlineDBReq))
		{
			MMOLOG_FMT_ERROR("account repeat login,  set db onlineflag error.... ");
			return false;
		}

		if (nullptr != pAccount->session)
		{
			//关闭客户端
			if (!g_GetLoginService()->CloseClient(pAccount->session))
			{
				MMOLOG_FMT_ERROR("[login] g_GetLoginService()->CloseClient failed....");
			}
		}
		pAccount->clear();
		g_GetAccountMgr()->DelOnlineAccount(strChannelUserID.c_str());
		g_GetAccountMgr()->FreeLoginAccountObj(pAccount);
	}
	return true;
}
//账号登录中心服验证返回
bool LoginLoginModule::CenterToLoginCheckRsp(RECV_PACKAGE &package)
{
	AccountLoginCheckRsp loginChecRsp;
	if (!loginChecRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[login] center rsp : AccountLoginCheckRsp parse failed...");
		return false;
	}
	uint32_t nTmpSessionID = loginChecRsp.session_id();
	std::string strChannelUserID = loginChecRsp.channel_user_id();
	LoginAccount *pLoginAccount = g_GetAccountMgr()->GetLoginAccount(strChannelUserID.c_str());
	if (nullptr == pLoginAccount)
	{
		//中心服返回时，登录账户不存在了
		MMOLOG_FMT_ERROR("[login]  center rsp : account[%s] login, center ret nullptr == pLoginAccount account...", strChannelUserID.c_str());
		return false;
	}
	if (nullptr == pLoginAccount->session)
	{
		//中心服返回时，客户端连接已经断开
		MMOLOG_FMT_ERROR(" [login] center rsp : account[%s] login, center ret nullptr == pLoginAccount->session...", strChannelUserID.c_str());
		return false;
	}
	const SESSION_USER_DATA &udata = pLoginAccount->session->GetUserData();
	if (udata.v32 != nTmpSessionID)
	{
		//当前session 和请求时的session不一样
		MMOLOG_FMT_ERROR(" [login] center rsp : [%s] login, udata.v32[%d] != nTmpSessionID[%d]...", strChannelUserID.c_str(), udata.v32, nTmpSessionID);
		return false;
	}

	uint64_t nTime = Time::Now().sec();
	uint64_t nInterVal = nTime - pLoginAccount->nTime;
	if (nInterVal > 3)
	{
		//到中心服验证返回时间超过 3 秒
		MMOLOG_FMT_WARN("[login] center rsp : 向中心服请求逻辑服信息返回时间超过[%lld]秒，账户：%s ", nInterVal, strChannelUserID.c_str());
	}
	if (pLoginAccount->byState != ACCOUNT_LOGIN_STATE_GET_GAME_SERVER)
	{
		MMOLOG_FMT_ERROR(" [login] center rsp : account login,state error,  account:%s, state:%d", strChannelUserID.c_str(), pLoginAccount->byState);
		return false;
	}

	//登录成功，设置在线标志
	AccountSetOnlineFlagDBRequest onlineDBReq;
	onlineDBReq.set_byonline(1);
	onlineDBReq.set_channel_user_id(strChannelUserID);
	if (!g_GetLoginService()->SendDataToDBProxy(EMODULE_ID_LOGIN, DBPROXY_PROTOCOL_ACCOUNT_SET_ONLINE_FALG_REQ, &onlineDBReq))
	{
		MMOLOG_FMT_ERROR("[login] center rsp : 账户[%s]登录,中心服返回逻辑服信息成功，DB设置账户在线状态失败...", strChannelUserID.c_str());
	}

	//设置登录成功状态
	pLoginAccount->byState = ACCOUNT_LOGIN_STATE_SUCCESS;
	pLoginAccount->nTime = nTime;

	//从登录map中移除
	g_GetAccountMgr()->DelLoginAccount(strChannelUserID.c_str());
	//加入到在线列表中
	g_GetAccountMgr()->AddOnlineAccount(strChannelUserID.c_str(), pLoginAccount);


	LogDebugFmtPrint("[login] center rsp:[%s] logic info, ip:%s , port:%d, token:%lld ", strChannelUserID.c_str(), loginChecRsp.logic_ip().c_str(), loginChecRsp.logic_port(), loginChecRsp.logic_token());
	//返回客户端 登录成功
	AccountLoginResponse loginRsp;
	loginRsp.set_retcode(RET_SUCCESS);
	loginRsp.set_groupid(loginChecRsp.group_id());
	loginRsp.set_logicip(loginChecRsp.logic_ip());
	loginRsp.set_logicport(loginChecRsp.logic_port());
	loginRsp.set_logictoken(loginChecRsp.logic_token());
	g_GetLoginService()->SendDataToClient(pLoginAccount->session, EMODULE_ID_LOGIN, LOGIN_TO_CLIENT_ACCOUNT_LOGIN, &loginRsp);

	return true;
}